home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / WAIS / next-ui / SourceDoc.m < prev    next >
Encoding:
Text File  |  1992-07-16  |  12.2 KB  |  418 lines

  1. // SourceDoc.m
  2. //
  3. // Free software created 1 Feb 1992
  4. // by Paul Burchard <burchard@math.utah.edu>.
  5.  
  6. #import "Wais.h"
  7. #import "WAISControl.h"
  8. #import "SourceDoc.h"
  9. #import "BrowserAssocTable.h"
  10. #import "IconWellControl.h"
  11. #import "IconWell.h"
  12. #import "MailSpeaker.h"
  13. #import "string.h"
  14. #import <appkit/appkit.h>
  15.  
  16.  
  17. @implementation SourceDoc
  18.  
  19. + (const char *)fileType
  20. {
  21.     return "src";
  22. }
  23.  
  24. + (const char *)nibName
  25. {
  26.     return "SourceDoc.nib";
  27. }
  28.  
  29. + (const char *)miniIconName
  30. {
  31.     return "WaisSource.tiff";
  32. }
  33.  
  34. + (const char *)defaultFolder
  35. {
  36.     return [[WaisSource folderList] elementAt:0];
  37. }
  38.  
  39. - updateFromWindow
  40. {
  41.     static char buf[READ_BUF_SIZE];
  42.     
  43.     [waisSource insertStringKey:":ip-name" value:[serverField stringValue]];
  44.     [waisSource insertStringKey:":tcp-port" value:[serviceField stringValue]];
  45.     [waisSource insertStringKey:":database-name"
  46.         value:[databaseField stringValue]];
  47.     [waisSource    insertStringKey:":cost"    value:[costField stringValue]];
  48.     [waisSource insertStringKey:":cost-unit" value:[unitsField stringValue]];
  49.     [waisSource insertStringKey:":maintainer"
  50.         value:[maintainerField stringValue]];
  51.     [[descriptionField docView] getSubstring:buf start:0 length:READ_BUF_SIZE];
  52.     [waisSource insertStringKey:":description" value:buf];
  53.     return self;
  54. }
  55.  
  56. - updateToWindow
  57. {
  58.     if([waisSource valueForStringKey:":ip-name"])
  59.     [serverField setStringValue:[waisSource valueForStringKey:":ip-name"]];
  60.     else if([waisSource valueForStringKey:":ip-address"])
  61.         [serverField setStringValue:[waisSource 
  62.             valueForStringKey:":ip-address"]];
  63.     else [serverField setStringValue:""];
  64.     if([waisSource valueForStringKey:":tcp-port"])
  65.         [serviceField setStringValue:[waisSource 
  66.         valueForStringKey:":tcp-port"]];
  67.     else [serviceField setStringValue:""];
  68.     if([waisSource valueForStringKey:":database-name"])
  69.         [databaseField setStringValue:[waisSource 
  70.         valueForStringKey:":database-name"]];
  71.     else [databaseField setStringValue:""];
  72.     if([waisSource valueForStringKey:":cost"])
  73.         [costField setStringValue:[waisSource valueForStringKey:":cost"]];
  74.     else [costField setStringValue:""];
  75.     if([waisSource valueForStringKey:":cost-unit"])
  76.         [unitsField setStringValue:[waisSource 
  77.         valueForStringKey:":cost-unit"]];
  78.     else [unitsField setStringValue:""];
  79.     if([waisSource valueForStringKey:":maintainer"])
  80.         [maintainerField setStringValue:[waisSource
  81.         valueForStringKey:":maintainer"]];
  82.     else [maintainerField setStringValue:""];
  83.     if([waisSource valueForStringKey:":description"])
  84.         [[descriptionField docView] setText:[waisSource 
  85.         valueForStringKey:":description"]];
  86.     else [[descriptionField docView] setText:""];
  87.     return self;
  88. }
  89.  
  90. - init
  91. {
  92.     [super init];
  93.     waisSource = [[WaisSource alloc] initKey:NULL];
  94.     [waisSource insertStringKey:":tcp-port" value:"210"];
  95.     [waisSource insertStringKey:":maintainer" value:current_user_name()];
  96.     [waisSource insertStringKey:":cost" value:"0"];
  97.     [waisSource insertStringKey:":cost-unit" value:":free"];
  98.     [[descriptionField docView] setDelegate:self];
  99.     isPublic = NO;
  100.     [self updateToWindow];
  101.     return self;
  102. }
  103.  
  104. - free
  105. {
  106.     [waisSource free];
  107.     [indexIWC free];
  108.     [indexPanel free];
  109.     return [super free];
  110. }
  111.  
  112. - dump:sender
  113. {
  114.     if(!fileName) return nil;
  115.     [self updateFromWindow];
  116.     if(![waisSource writeWaisFile]) return nil;
  117.     return self;
  118. }
  119.  
  120. - load:sender
  121. {
  122.     if(!fileName) return nil;
  123.     if(![waisSource readWaisFile]) return nil;
  124.     [self updateToWindow];
  125.     return self;
  126. }
  127.  
  128. - setFileName:(const char *)aName
  129. {
  130.     id rtn = [super setFileName:aName];
  131.     if(rtn) [waisSource setKey:fileName];
  132.     return(rtn);
  133. }
  134.  
  135. - (int)openFile:(const char *)name ok:(int *)flag
  136. {
  137.     return [[NXApp delegate] openFile:name ok:flag];
  138. }
  139.  
  140. - bugReport:sender
  141. {
  142.     //!!! Note the "MailSendDemo" port is undocumented.
  143.     id mailSpeaker = [[MailSpeaker alloc] init]; 
  144.     port_t mailPort = NXPortFromName("MailSendDemo", NULL); 
  145.     const char *maint;
  146.  
  147.     maint = [waisSource valueForStringKey:":maintainer"];
  148.     if(!maint || !maint[0]) return nil;
  149.     if(!mailSpeaker || mailPort==PORT_NULL)
  150.         { [mailSpeaker free]; return nil; }
  151.     [mailSpeaker setSendPort:mailPort];
  152.     [mailSpeaker openSend];
  153.     [mailSpeaker setTo:maint];
  154.     if([waisSource valueForStringKey:":database-name"])
  155.     [mailSpeaker setSubject:[waisSource 
  156.         valueForStringKey:":database-name"]];
  157.     [mailSpeaker free];
  158.     port_deallocate(task_self(), mailPort); 
  159.     return self;
  160. }
  161.  
  162. - indexPanel:sender
  163. {
  164.     int i, j, n, choice;
  165.     id data, stringTable;
  166.     const char *maint, *user;
  167.  
  168.     // Just pop up panel if it already exists.
  169.     if(indexPanel)
  170.     { [indexPanel makeKeyAndOrderFront:self]; return indexPanel; }
  171.  
  172.     // Allow user to cancel if overwriting someone else's source.
  173.     maint = [waisSource valueForStringKey:":maintainer"];
  174.     user = current_user_name();
  175.     stringTable = [[NXApp delegate] stringTable];
  176.     if(maint && user && strcmp(maint, user)!=0)
  177.     {
  178.     if(stringTable) choice = NXRunAlertPanel(
  179.         [stringTable valueForStringKey:"Warning!"],
  180.             [stringTable valueForStringKey:"This database is maintained by %s.  Are you sure you want to overwrite it?"],
  181.         [stringTable valueForStringKey:"Yes"],
  182.         [stringTable valueForStringKey:"Cancel"], NULL, maint);
  183.     else
  184.     {
  185.         fprintf(stderr,
  186.             "Warning!  Overwriting WAIS source maintained by %s\n", maint);
  187.         fflush(stderr);
  188.         choice = NX_ALERTDEFAULT;
  189.     }
  190.     if(choice != NX_ALERTDEFAULT) return nil;
  191.     }
  192.     
  193.     // Make user save new source first.
  194.     if(!fileName)
  195.     {
  196.         if(![[NXApp delegate] saveDoc:self as:YES]) return nil;
  197.     if(!fileName) return nil;
  198.     }
  199.     {//!!!
  200.     char *extn;
  201.     char hostname[1024];
  202.     //!!! messing with uniqued strings
  203.     if(!(extn = strrchr(fileName, '/'))) extn = fileName;
  204.     if(!(extn = strrchr(extn, '.'))) return nil;
  205.     if(strcmp(extn+1, [[self class] fileType]) != 0) return nil;
  206.     *extn = 0;
  207.     [waisSource insertStringKey:":database-name" value:fileName];
  208.     *extn = '.';
  209.     gethostname(hostname, 1024);
  210.     [waisSource insertStringKey:":ip-name" value:hostname];
  211.     if(![waisSource writeWaisFile]) return nil;
  212.     [self updateToWindow];
  213.     }
  214.  
  215.     // Otherwise, load NIB and indexing information.
  216.     [NXApp loadNibSection:"Indexer.nib" owner:self];
  217.     [indexInputWell setDraggable:YES droppable:YES];
  218.     [indexScriptWell setDraggable:YES droppable:NO];
  219.     [[[indexFiles setEditable:YES] setAlphabetized:NO] setAbbreviated:NO];
  220.     [indexFiles setTarget:self];
  221.     [[indexFiles setAction:@selector(updateSelection:)]
  222.         setDoubleAction:@selector(updateSelection:)];
  223.     n = [[waisSource dataFileList] count];
  224.     for(i=0; i<n; i++)
  225.     {
  226.         data = [[waisSource dataFileList] objectAt:i];
  227.     j = [indexFiles indexAddEntry:[data valueForStringKey:"data-file"]];
  228.     [indexFiles
  229.         setAssocStringValue:[data valueForStringKey:":index-mode"] at:j];
  230.     }
  231.  
  232.     // Now pop up new panel.
  233.     [indexPanel makeKeyAndOrderFront:self];
  234.     if(!indexIWC) indexIWC = [[IconWellControl alloc] initWindow:indexPanel];
  235.     return self;
  236. }
  237.  
  238. - addToIndex:sender
  239. {
  240.     id theTarget;
  241.     SEL theAction;
  242.  
  243.     theTarget = [indexFiles target];
  244.     theAction = [indexFiles action];
  245.     [indexFiles setTarget:nil];
  246.     [indexFiles setAction:(SEL)0];
  247.     [indexFiles setStringValue:[indexInputWell stringValue]];
  248.     [indexFiles setTarget:theTarget];
  249.     [indexFiles setAction:theAction];
  250.     return [self applyIndexMode:self];
  251. }
  252.  
  253. - applyIndexMode:sender
  254. {
  255.     int i, n;
  256.     const char *mode = [[indexMode target] selectedItem];
  257.     
  258.     if(!mode) mode = ":text";
  259.     n = [indexFiles count];
  260.     for(i=0; i<n; i++) if([indexFiles isEntrySelectedAt:i])
  261.         [indexFiles setAssocStringValue:mode at:i];
  262.     return self;
  263. }
  264.  
  265. - makePrivate:sender
  266. {
  267.     isPublic = NO;
  268.     return self;
  269. }
  270.  
  271. - makePublic:sender
  272. {
  273.     //!!!----DISABLED-----
  274.     NXRunAlertPanel("Publication",
  275.         "Sorry, Internet publication has been disabled in this version.",
  276.     "OK", NULL, NULL);
  277.     return nil;
  278.     
  279.     /*!!!
  280.     int choice;
  281.     id stringTable;
  282.  
  283.     // Let user cancel Internet publication.
  284.     if(!(stringTable = [[NXApp delegate] stringTable])) return nil;
  285.     choice = NXRunAlertPanel(
  286.     [stringTable valueForStringKey:"Warning!"],
  287.     [stringTable valueForStringKey:"Continuing will cause this source to be published on the Internet.  Make sure public access has been enabled!  Proceed?"],
  288.     [stringTable valueForStringKey:"OK"],
  289.     [stringTable valueForStringKey:"Cancel"], NULL);
  290.     if(choice == NX_ALERTALTERNATE)
  291.         { [indexPrivate performClick:self]; return nil; }
  292.     isPublic = YES;
  293.     return self;
  294.     */
  295. }
  296.  
  297. - updateSelection:sender
  298. {
  299.     id theTarget;
  300.     SEL theAction;
  301.  
  302.     theTarget = [indexInputWell target];
  303.     theAction = [indexInputWell action];
  304.     [indexInputWell setTarget:nil];
  305.     [indexInputWell setAction:(SEL)0];
  306.     [indexInputWell setStringValue:[indexFiles stringValue]];
  307.     [indexInputWell setTarget:theTarget];
  308.     [indexInputWell setAction:theAction];
  309.     return self;
  310. }
  311.  
  312. - createIndex:sender
  313. {
  314.     int i, j, n, start_at, ok;
  315.     char *extn;
  316.     const char *mode;
  317.     const char *systemFolder = NXGetDefaultValue("WAIStation","SystemFolder");
  318.     id data;
  319.     FILE *cmdfile;
  320.     BOOL first;
  321.     
  322.     // Reset source's :index-list and save.
  323.     //!!! waisindex overwrites this!!!
  324.     if(!fileName) return nil;
  325.     [waisSource clearDataFiles];
  326.     n = [indexFiles count];
  327.     for(i=0; i<n; i++)
  328.     {
  329.         data = [[WaisDataFile alloc] initKey:NULL];
  330.     [data insertStringKey:":data-file" value: [indexFiles entryAt:i]];
  331.     [data insertStringKey:":index-mode"    
  332.         value: [indexFiles assocStringValueAt:i]];
  333.     [waisSource addDataFile:data];
  334.     }
  335.     if(![self dump:self]) return nil;
  336.  
  337.     // Create shell script to index the data files.
  338.     //!!! How 'bout some alert panels here??
  339.     //!!! messing with uniqued strings
  340.     if(!fileName) return nil;
  341.     if(!(extn = strrchr(fileName, '/'))) extn = fileName;
  342.     if(!(extn = strrchr(extn, '.'))) return nil;
  343.     if(strcmp(extn+1, [[self class] fileType]) != 0) return nil;
  344.     [Wais lockFileIO];
  345.     strcpy(extn+1, "sh");
  346.     if(!(cmdfile = fopen(fileName, "w")))
  347.         { [Wais unlockFileIO]; return nil; }
  348.     strcpy(extn+1, [[self class] fileType]);
  349.     fchmod(fileno(cmdfile), 0755);
  350.     
  351.     // Write script header info.
  352.     fprintf(cmdfile, "#!/bin/sh\n");
  353.     fprintf(cmdfile, "# WAIS indexing script for %s\n", fileName);
  354.     fprintf(cmdfile, "# Created %s by WAIStation.app %s\n",
  355.         printable_time(), WAISTATION_VERSION);
  356.     
  357.     // Group data files with same :mode into waisindex commands.
  358.     //!!! Should keep command length below some limit.
  359.     //!!! What about data file names with '\'' chars???
  360.     n = [indexFiles count];
  361.     for(first=YES, mode=0, start_at=0;
  362.         start_at>=0 && start_at<n; mode=0, first=NO)
  363.         for(i=start_at, start_at=(-1); i<n; i++)//!!!
  364.     {
  365.         if(!mode)
  366.     {
  367.         // Starting new :mode.  Flush old cmd line and start new one.
  368.         mode = [indexFiles assocStringValueAt:i];
  369.         *extn = 0;
  370.         fprintf(cmdfile, "\n%s/bin/waisindex -d %s %s -r -export ",
  371.             (systemFolder ? systemFolder : ""),
  372.         fileName, (first ? "" : "-a"));
  373.         *extn = '.';
  374.         if(isPublic) fprintf(cmdfile, "-register ");
  375.         if(!mode || !mode[0]) fprintf(cmdfile, "-t text ");        
  376.         else fprintf(cmdfile, "-t %s ", mode+1);        
  377.     }
  378.     else if(strcmp(mode, [indexFiles assocStringValueAt:i]) != 0)
  379.     {
  380.         // Check if we saw this before.
  381.         for(j=0; j<i; j++)
  382.             if(strcmp([indexFiles assocStringValueAt:i],
  383.             [indexFiles assocStringValueAt:j]) == 0)
  384.                 break;
  385.         if(j < i) continue;
  386.         
  387.         // Found new :mode.  Skip file and set pointer for next loop.
  388.         if(start_at < 0) start_at = i;
  389.         continue;
  390.     }
  391.     if(!mode || strlen(mode)==0) { [Wais unlockFileIO]; return nil; }
  392.     
  393.     // Compile data file into command line.
  394.     fprintf(cmdfile, "\'%s\' ", [indexFiles entryAt:i]);
  395.     }
  396.     // Flush last cmd line.
  397.     fprintf(cmdfile, "\n");
  398.     
  399.     // Have script refresh source in WAIStation by re-opening.
  400.     //!!! Check if WS running first?
  401.     fprintf(cmdfile, "open %s\n", fileName);
  402.     fclose(cmdfile);
  403.     [Wais unlockFileIO];
  404.     
  405.     // Now run script and present it to the user for re-indexing.
  406.     ok = NO;
  407.     strcpy(extn+1, "sh");
  408.     [indexScriptWell setStringValue:fileName];
  409.     [self openFile:fileName ok:&ok];
  410.     strcpy(extn+1, [[self class] fileType]);
  411.     if(!ok) return nil;
  412.     return self;
  413. }
  414.  
  415. @end
  416.  
  417.  
  418.